<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>手写Promise-class版</title>
  </head>
  <body>
    <script>
      // 手写promise实现步骤：1.构造函数 2.状态及原因 3.then方法 4.异步任务执行 5.链式调用

      const PENDING = "pending";
      const FULFILLED = "fulfilled";
      const REJECTED = "rejected";
      class myPromise {
        status = PENDING;
        result = undefined;

        #handler = []; // [{onFulfilled,onRejected}]
        constructor(fn) {
          const resolve = (result) => {
            if (this.status === PENDING) {
              this.status = FULFILLED;
              this.result = result;
              this.#handler.forEach(({ onFulfilled }) => {
                onFulfilled(this.result);
              });
            }
          };
          const reject = (result) => {
            if (this.status === PENDING) {
              this.status = REJECTED;
              this.result = result;
              this.#handler.forEach(({ onRejected }) => {
                onRejected(this.result);
              });
            }
          };
          fn(resolve, reject);
        }
        then(onFulfilled, onRejected) {
          onFulfilled =
            typeof onFulfilled === "function" ? onFulfilled : (value) => value;
          onRejected =
            typeof onRejected === "function"
              ? onRejected
              : (reason) => {
                  throw reason;
                };

          const p2 = new myPromise((resolve, reject) => {
            if (this.status === FULFILLED) {
              runAsyncTask(() => {
                try {
                  const val = onFulfilled(this.result);
                  //   console.log(val)
                  // TypeError: Chaining cycle detected for promise #<Promise>
                  // 处理重复引用
                  resolvePromise(val, p2, resolve, reject);
                  //   console.log("val",val)
                } catch (error) {
                  reject(error);
                }
              });
            } else if (this.status === REJECTED) {
              runAsyncTask(() => {
                try {
                  const val = onRejected(this.result);
                  resolvePromise(val, p2, resolve, reject);
                } catch (error) {
                  reject(error);
                }
              });
            } else if (this.status === PENDING) {
              this.#handler.push({
                onFulfilled: () => {
                  runAsyncTask(() => {
                    try{
                       const val =  onFulfilled(this.result);
                       resolvePromise(val, p2, resolve, reject);
                    }catch(error){
                        reject(error)
                    }
                  });
                },
                onRejected: () => {
                  runAsyncTask(() => {
                    try{
                      const val = onRejected(this.result);
                      resolvePromise(val, p2, resolve, reject);
                    }catch(error){
                        reject(error)
                    }
                    
                  });
                },
              });
            }
          });

          return p2;
        }
      }
      //   console.log("1");
      const p = new myPromise((resolve, reject) => {
        setTimeout(() => {
            // resolve("成功了");
            reject("失败了");
        }, 2000);
        // resolve("成功了");
        // reject("errorrr");
      });
      const p1 = p.then(
        res=>{
        //    return "11"
        // return p1;
        // return new myPromise((resolve,reject)=>{
            // resolve("111")
            // reject("111")
        // })
        },
        (err) => {
            // return "11111"
            // return p1
        //   console.log("reson1", err);
        //   return "3co"
        // return p1
        return new myPromise((resolve,reject)=>{
            // resolve("333")
            // reject("eeeeee")
        })
        }
      );
      const p2 = p1.then(
        (res) => {
          console.log("then2", res);
        },
        (err) => {
          console.log("reson2", err);
        }
      );
      //   console.log("3");

      // 用来执行异步的任务
      function runAsyncTask(callback) {
        setTimeout(() => {
          callback();
        }, 0);
      }

      function resolvePromise(val, p2, resolve, reject) {
        if (val === p2) {
          throw new TypeError("Chaining cycle detected for promise #<Promise>");
        }
        if (val instanceof myPromise) {
          val.then(
            (res) => {
              resolve(res);
            },
            (rej) => {
              reject(rej);
            }
          );
        } else {
          resolve(val);
        }
      }

      // p.then((value)=>{
      //   console.log("then2",value)
      // },(reson)=>{
      //   console.log("reson2",reson)
      // })
      // console.log("3");
      // console.log(p)

      /* queueMicrotask 用于将微任务（microtask）加入微任务队列
    console.log("1")
    queueMicrotask(()=>{
        console.log("queueMicrotask")
    })
    console.log("3") */
      /* MutationObserver 用来监测dom树的变化
    console.log("1")  
    const obs = new MutationObserver(()=>{
        console.log("MutationObserver")
    })
    const divNode = document.createElement("div");
    obs.observe(divNode,{
        childList:true
    })
    divNode.innerHTML = "123"
    console.log("3") */
    </script>
  </body>
</html>
